/**
 * 
 */
package co.edu.javeriana.ia.ga;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.List;
import java.util.Map;

import org.jgap.Chromosome;
import org.jgap.Configuration;
import org.jgap.Genotype;
import org.jgap.IChromosome;
import org.jgap.InvalidConfigurationException;

import co.edu.javeriana.ia.ga.fittness.GenClassificationFittness;
import co.edu.javeriana.ia.ga.readers.DescriptorReader;
import co.edu.javeriana.ia.ga.readers.GenomeReader;
import co.edu.javeriana.ia.ga.readers.SecuenceReader;

/**
 * <p>
 * Clase principal para configurar JGAP
 * </p>
 * 
 * @author <a href=f.triana@javeriana.edu.co">Alejandro Triana</a>
 * @version 1.0
 */
public class Principal {

	private GenClassificationFittness geFunc;

	/**
	 * <p>
	 * Funcion de Inicio del algoritmo
	 * </p>
	 */
	public static void main(String[] args) {

		try {

			PrintStream print = new PrintStream(new FileOutputStream(
					Constants.FILE_LOG));

			System.setOut(print);
			Principal p = new Principal();

			Configuration conf = p.setUpJgap();

			p.runGa(conf);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * <p>
	 * Permite probar el mejor cromosoma
	 * </p>
	 */
	public void testBestChromosome(IChromosome chr) {
		@SuppressWarnings("unused")
		double fittnest = geFunc.evaluateTest(chr, true);
	}

	/**
	 * <p>
	 * Establece la configuracion correcta de JGap
	 * </p>
	 */
	public Configuration setUpJgap() {

		try {

			Configuration configuration = new GenConfiguration();

			File flDescriptors = new File(Constants.DESCRIPTORS_FILE);

			// Lectura de los archivos de datos
			Map<String, Descriptor> descriptors = DescriptorReader
					.readDescriptors(flDescriptors);
			GenomeReader.instance.setFlGenomes(new File(Constants.GENOME_FILE),
					descriptors);

			List<Secuence> secuences = getSequences(descriptors,
					Constants.SEQUENCE_FILE);

			return buildConfiguration(configuration, secuences);

		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}

	}

	/**
	 * <p>
	 * Construccion configuracion de JGap
	 * </p>
	 */
	private Configuration buildConfiguration(Configuration configuration,
			List<Secuence> secuences) throws InvalidConfigurationException {

		this.geFunc = new GenClassificationFittness(secuences);

		configuration.setFitnessFunction(geFunc);

		// Creacion del Cromosoma de Ejemplo
		Chromosome cromosome = ChromosomeFactory
				.createChromosomes(configuration);

		configuration.setSampleChromosome(cromosome);
		configuration.setPopulationSize(Constants.POPULATION_SIZE);

		return configuration;
	}

	/**
	 * <p>
	 * Obtiene el listado de secuencias para los genomas
	 * </p>
	 */
	private List<Secuence> getSequences(Map<String, Descriptor> descriptors,
			String sequencesFile) {

		File fileSecuence = new File(sequencesFile);

		List<Secuence> secuences = SecuenceReader.getSecuencesForFile(
				descriptors, fileSecuence);

		return secuences;
	}

	/**
	 * <p>
	 * Realiza una corrida del algoritmo genetico, para un proceso de
	 * clasificacion
	 * </p>
	 */
	public void runGa(Configuration configuration)
			throws InvalidConfigurationException {

		Genotype genotype = Genotype.randomInitialGenotype(configuration);
		
		PrintUtil.printString("Evolving the population\n");

		for (int m = 0; m < Constants.ITERATIONS; m++) {

			genotype.evolve();

			IChromosome fittestChr = (Chromosome) genotype
					.getFittestChromosome();

			PrintUtil.printIteration(m);
			PrintUtil.printChromosome(fittestChr);

			testBestChromosome(fittestChr);
		}
	}

	
}
